<?php

declare(strict_types=1);

namespace So\App\Controller\Backend;

use Hyperf\HttpServer\Annotation\DeleteMapping;
use Hyperf\HttpServer\Annotation\PutMapping;
use Hyperf\HttpServer\Annotation\PostMapping;
use Psr\Http\Message\ResponseInterface;
use So\Annotation\AdminLog;
use So\Controller\Backend;
use So\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use So\Annotation\Auth;
use So\Exception\ControllerException;
use So\Library\Tree;
use So\Library\Auth as AuthLib;
use Hyperf\Di\Annotation\Inject;
use So\Annotation\Validation;
use So\Annotation\Model;
use Hyperf\DbConnection\Db;
use So\Library\Random;

/**
 * @Controller(prefix="admin")
 * @Auth(nocheck={"admin/getGroups"})
 * @AdminLog({"admin/getLogs"})
 */
class AdminController extends Backend
{
    /**
     * @Inject()
     * @var AuthLib
     */
    protected $auth;

    /**
     * @GetMapping("read")
     * @Model
     */
    public function read($model): ResponseInterface
    {

        if (!$this->auth->id){
            var_dump($this->auth->id);
            var_dump($this->auth->getError());die;
        }
        $childrenAdminIds = $this->auth->getChildrenAdminIds($this->auth->isSuperAdmin($this->auth->id));
        $childrenGroupIds = $this->auth->getChildrenGroupIds($this->auth->isSuperAdmin($this->auth->id));

        $groupName = Db::table('auth_group')->whereIn('id', $childrenGroupIds)
            ->pluck('name', 'id');
        $authGroupList = Db::table('auth_group_access')->whereIn('group_id', $childrenGroupIds)
            ->select('uid', 'group_id')
            ->get();
        $adminGroupName = [];
        foreach ($authGroupList as $k => $v) {
            if (isset($groupName[$v['group_id']])) {
                $adminGroupName[$v['uid']][$v['group_id']] = $groupName[$v['group_id']];
            }
        }
        $groups = $this->auth->getGroups($this->auth->id);
        foreach ($groups as $m => $n) {
            $adminGroupName[$this->auth->id][$n['id']] = $n['name'];
        }
        $list = $this->where($model)->whereIn('id', $childrenAdminIds)->orderBy($model->sortPk, $model->sortBy)->paginate($model->pageSize);
        foreach ($list as $k => &$v) {
            $groups = isset($adminGroupName[$v['id']]) ? $adminGroupName[$v['id']] : [];
            $v['groups'] = array_keys($groups);
            $v['groups_text'] = implode("\r\n", array_values($groups));
            unset($v['password'], $v['salt']);
        }
        unset($v);

        return $this->success("", [
            'page' => $list->currentPage(),
            'pageSize' => $model->pageSize,
            'rows' => $list->items(),
            'total' => $list->total(),
        ]);
    }

    /**
     * @GetMapping("getLogs")
     */
    public function getLogs()
    {
        $where = [
            'username' => $this->auth->username,
        ];
        $search = input('search/s');
        if ($search) {
            $cloumn = ['url', 'title', 'content', 'ip'];
            foreach ($cloumn as $v) {
                $where[] = [$v, 'like', '%' . $search . '%', 'OR'];
            }
        }
        $list = Db::table('admin_log')->where($where)->orderBy('id', 'desc')->paginate(10);
        return $this->success("", [
            'page' => $list->currentPage(),
            'pageSize' => 10,
            'rows' => $list->items(),
            'total' => $list->total(),
        ]);
    }

    /**
     * @GetMapping("getGroups")
     * @Model
     */
    public function getGroups($model): ResponseInterface
    {
        $childrenGroupIds = $this->auth->getChildrenGroupIds($this->auth->isSuperAdmin($this->auth->id));
        $groupList = Db::table('auth_group')->whereIn('id', $childrenGroupIds)->select('id', 'name', 'pid')->get()->toArray();
        Tree::instance()->init($groupList, 'pid', ' ');
        $groupdata = [];
        if ($this->auth->isSuperAdmin($this->auth->id)) {
            $result = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0));
            foreach ($result as $k => $v) {
                $groupdata[] = $v;
            }
        } else {
            $result = [];
            $groups = $this->auth->getGroups($this->auth->id);
            foreach ($groups as $m => $n) {
                $childlist = Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n['id']));
                $temp = [];
                foreach ($childlist as $k => $v) {
                    $temp[] = $v;
                }
            }
            $groupdata = $temp;
        }
        return $this->success('', $groupdata);
    }

    /**
     * @DeleteMapping("delete")
     * @Model
     */
    public function delete($data, $model): ResponseInterface
    {
        return parent::delete($data, $model);
    }

    /**
     * @PostMapping("operate")
     * @Model
     */
    public function operate($model): ResponseInterface
    {
        return parent::operate($model);
    }

    /**
     * @PostMapping("create")
     * @Validation
     * @Model
     */
    public function create($data, $model): ResponseInterface
    {
        Db::beginTransaction();
        try {
            $data['salt'] = Random::alnum();
            $data['password'] = md5(md5($data['password']) . $data['salt']);
            $data['avatar'] = '/assets/img/avatar.png';
            $group = $data['groups'];
            unset($data['groups']);
            $childrenGroupIds = $this->auth->getChildrenGroupIds($this->auth->isSuperAdmin($this->auth->id));
            $group = array_intersect($childrenGroupIds, $group);
            if (!$group) {
                throw new ControllerException('父组别超出权限范围');
            }
            foreach ($data as $k => $v) {
                $model->{$k} = $v;
            }
            $create = $model->save();
            if (!$create) {
                throw new ControllerException('创建失败');
            }
            $id = $model->{$model->getPk()};
            $dataset = [];
            foreach ($group as $value) {
                $dataset[] = ['uid' => $id, 'group_id' => $value];
            }
            Db::table('auth_group_access')->insert($dataset);
            Db::commit();
        } catch (ControllerException $e) {
            Db::rollBack();
            return $this->error($e->getMessage());
        } catch (Exception $e) {
            Db::rollBack();
            return $this->error($this->isDev ? $e->getMessage() : "创建出错");
        }
        return $this->success('创建成功');
    }

    /**
     * @PutMapping("update")
     * @Validation
     * @Model
     */
    public function update($data, $model): ResponseInterface
    {
        Db::beginTransaction();
        try {
            if ($data['password']) {
                $data['salt'] = Random::alnum();
                $data['password'] = md5(md5($data['password']) . $data['salt']);
            } else {
                unset($data['password'], $data['salt']);
            }
            $row = $model::query()->find($data['id']);
            if (!$row) {
                throw new ControllerException('查询不存在');
            }
            $group = $data['groups'];
            unset($data['groups']);
            unset($data['id']);
            foreach ($data as $k => $v) {
                $row->{$k} = $v;
            }
            $update = $row->save();
            Db::table('auth_group_access')->where('uid', '=', $row->id)->delete();
            $childrenGroupIds = $this->auth->getChildrenGroupIds($this->auth->isSuperAdmin($this->auth->id));
            $group = array_intersect($childrenGroupIds, $group);
            if (!$group) {
                throw new ControllerException('父组别超出权限范围');
            }
            $dataset = [];
            foreach ($group as $value) {
                $dataset[] = ['uid' => $row->id, 'group_id' => $value];
            }
            Db::table('auth_group_access')->insert($dataset);
            Db::commit();
        } catch (ControllerException $e) {
            Db::rollBack();
            return $this->error($e->getMessage());
        } catch (Exception $e) {
            Db::rollBack();
            return $this->error($this->isDev ? $e->getMessage() : "更新出错");
        }
        if ($update) {
            return $this->success('更新成功', $data);
        }
        return $this->error('更新失败');
    }

    protected function _delete($ids, $model)
    {
        $childrenAdminIds = $this->auth->getChildrenAdminIds($this->auth->isSuperAdmin($this->auth->id));
        $childrenGroupIds = $this->auth->getChildrenGroupIds($this->auth->isSuperAdmin($this->auth->id));
        $ids = array_intersect($childrenAdminIds, array_filter($ids));
        $query = Db::table('auth_group_access')->whereIn('group_id', $childrenGroupIds)->select('uid')->pluck('uid')->toArray();
        $adminList = $model::query()->whereIn('id', $ids)->whereIn('id', $query)->get()->toArray();
        if ($adminList) {
            $deleteIds = [];
            foreach ($adminList as $k => $v) {
                $deleteIds[] = $v['id'];
            }
            $deleteIds = array_values(array_diff($deleteIds, [$this->auth->id]));
            if ($deleteIds) {
                $ids = array_merge($ids, $deleteIds);
                Db::table('auth_group_access')->whereIn('uid', $deleteIds)->delete();
            }
        }
        return $ids;
    }
}